﻿using Numbers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using Microsoft.Silverlight.Testing;

namespace t_Numbers
{
    /// <summary>
    ///This is a test class for t_Value and is intended
    ///to contain all t_Value Unit Tests
    ///</summary>
    [TestClass]
    public class t_Value
    {
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for Val
        ///</summary>
        [TestMethod()]
        public void TestVal()
        {
            Value target = new Value(); // TODO: Initialize to an appropriate value
            Assert.AreEqual(0.0, target.Val, "Expected it to init to 0");
            Assert.IsFalse(target.MaxValue.HasValue, "Expected no value for max value");
            Assert.IsFalse(target.MinValue.HasValue, "Expected no value for min value");
        }

        [TestMethod]
        public void TestValSetting()
        {
            Value t = new Value();
            t.Val = 5.0;
            Assert.AreEqual(5.0, t.Val, "Expected the value to be 5");
            t.Val = 100000.0;
            Assert.AreEqual(100000.0, t.Val, "Expected to be 1000000");
            t.Val = -5.0;
            Assert.AreEqual(-5.0, t.Val, "Expected -5");
        }

        /// <summary>
        ///A test for MinValue
        ///</summary>
        [TestMethod()]
        public void TestMinValue()
        {
            Value target = new Value(); // TODO: Initialize to an appropriate value
            target.MinValue = 0.0;
            target.Val = 5.0;
            Assert.AreEqual(5.0, target.Val, "Expected 5.0 no problem");

            target.Val = -10.0;
            Assert.AreEqual(0.0, target.Val, "Expected 0.0 to have been reset!");

            target.MinValue = 10.0;
            Assert.AreEqual(10.0, target.Val, "Expected to have been lifted to 10.0");

            target.MinValue = null;
            Assert.AreEqual(10.0, target.Val, "Changing min value to null should not have erased it");

            target.Val = 0.0;
            Assert.AreEqual(0.0, target.Val, "No limits - should set just fine!");
        }

        /// <summary>
        ///A test for MaxValue
        ///</summary>
        [TestMethod()]
        public void TestMaxValue()
        {
            Value target = new Value(); // TODO: Initialize to an appropriate value
            target.MaxValue = 1.0;
            target.Val = 0.5;
            Assert.AreEqual(0.5, target.Val, "Expected 0.5 no problem");

            target.Val = 5.0;
            Assert.AreEqual(1.0, target.Val, "Expected 1.0 to have been reset!");

            target.MaxValue = 0.3;
            Assert.AreEqual(0.3, target.Val, "Expected to have been lifted to 0.3");

            target.MaxValue = null;
            Assert.AreEqual(0.3, target.Val, "Changing min value to null should not have erased it");

            target.Val = 10.0;
            Assert.AreEqual(10.0, target.Val, "No limits - should set just fine!");
        }

        [TestMethod]
        public void TestChanged()
        {
            Value v = new Value();
            int count = 0;
            v.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler((o, arg) => { count = count + 1; });

            v.Val = 10;
            Assert.AreEqual(1, count, "Should have been an update!");
            v.Val = 10;
            Assert.AreEqual(1, count, "Should not have been called when same thing is changed!");

            v.MaxValue = 5;
            Assert.AreEqual(2, count, "Should have been updated when we changed max value!");
        }

        [TestMethod]
        public void TestUpdateNotification()
        {
            Value v = new Value();
            v.TransactionManager = new Numbers.Transactions.Manager();
            int countPC = 0;
            v.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler((o, arg) => { countPC = countPC + 1; });
            int countPPC = 0;
            v.ProposedPropertyChange += new Numbers.Transactions.ProposedPropertyChangeCallback((o, arg) =>
            {
                countPPC += 1;
                Assert.IsTrue(v.TransactionManager.InTransaction, "Should be in a transaction for proposed change call back!");
                return true;
            });

            using (var dis = new Value.DisableNotifications(v, 10.0))
            {
                Assert.AreEqual(0, countPC, "Didn't expect a notification to run!");
                Assert.AreEqual(0, countPPC, "Didn't expect a proposed notification either!");
            }
            Assert.AreEqual(1, countPPC, "Did expect a proposed notification as well");
            Assert.AreEqual(1, countPC, "Expected a notification!");
        }

        [TestMethod]
        public void TestUpdateWithNoChange()
        {
            Value v = new Value();
            int countPC = 0;
            v.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler((o, arg) => {
                countPC = countPC + 1;
            });

            v.Val = 10.0;
            countPC = 0;
            using (var dis = new Value.DisableNotifications(v, 10.0))
            {
            }
            Assert.AreEqual(0, countPC, "Didn't expect a non-change to generate a update notification!");
        }

        [TestMethod]
        public void TestValueRegistry()
        {
            Value t = new Value("dude");
            t.Val = 5.0;

            Value z = Value.FindValue("dude");
            Assert.IsNotNull(z, "Expected to find dude!");
            Assert.AreEqual(5.0, z.Val, "Expected the values to be the same");

            z.Val = 7.0;
            Assert.AreEqual(7.0, t.Val, "Not really the same!?");

            Assert.IsNull(Value.FindValue("fork"), "non-existant name should not have been returned");
        }

    }
}
